package com.tools.cleanmaster.manager;

import android.app.AlarmManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Handler;
import android.os.HandlerThread;
import android.text.TextUtils;
import android.text.format.DateUtils;

import com.tools.cleanmaster.CleanApplication;
import com.tools.cleanmaster.CleanConstant;
import com.tools.cleanmaster.receiver.ScenePeriodTaskReceiver;
import com.tools.cleanmaster.receiver.SceneScreenSwitchReceiver;
import com.tools.cleanmaster.scenenew.SceneBatteryChange;
import com.tools.cleanmaster.scenenew.SceneConstants;
import com.tools.cleanmaster.scenenew.ScenePriority;
import com.tools.cleanmaster.scenenew.SceneToolkit;
import com.tools.cleanmaster.scenenew.SceneType;
import com.tools.cleanmaster.store.SceneSharedPrefManager;
import com.tools.cleanmaster.ui.notification.NotificationBaseItem;
import com.tools.cleanmaster.ui.notification.item.TotalCpuUtilizationItem;
import com.tools.cleanmaster.utils.FeatureConfig;
import com.tools.cleanmaster.utils.LogHelper;

import java.net.URI;
import java.util.Calendar;

/**
 * 整体控制通知栏展示
 */
public class NotificationSceneManager {
    public static final String TAG = "Scene";
    private static final boolean DEBUG = FeatureConfig.DEBUG_LOG;

    public static final String ACTION_SCENE_DELETE = CleanConstant.REAL_PACKAGE_NAME + ".action_noti_delete";
    public static final String ACTION_SCENE_TASK_RESTART = CleanConstant.REAL_PACKAGE_NAME + ".action_scene_task_restart";
    public static final String ACTION_SCENE_CPU_TASK = CleanConstant.REAL_PACKAGE_NAME + ".action.cputask";

    public static final int NOTIFICATION_ID = 1024;
    public static final int APLUS_NOTIFICATIONID = 1027;
    public static final int APPLCEAN_NOTIFICATION_ID = 1028;


    private Context mContext;
    private NotificationManager mNotifyManage;
    private String mNetflowShowPkg = "";//场景频繁调用网络，弹出消息时记录包名，卸载时要移除通知

    private static NotificationSceneManager mManagerInstance;
    private Handler mHandler;
    private Handler mAPlusHandler;

    BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (ACTION_SCENE_DELETE.equals(action)) {
                SceneSharedPrefManager.setCurrentShowSceneType(null);
            } else if (ACTION_SCENE_TASK_RESTART.equals(action)) {
                long now = System.currentTimeMillis();
                long restartTime = SceneSharedPrefManager.getSceneRestartTime();
                if (restartTime != 0 && now >= restartTime) {
                    restart();
                }
            } else if (ACTION_SCENE_CPU_TASK.equals(action)) {
                cpuScan();
            }
        }
    };

    private NotificationSceneManager() {
        mContext = CleanApplication.getInstance();
        mNotifyManage = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
        HandlerThread handlerThread = new HandlerThread("SceneBgThread");
        handlerThread.start();
        mHandler = new Handler(handlerThread.getLooper());
        mAPlusHandler = new Handler(handlerThread.getLooper());
    }

    private void init() {
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(ACTION_SCENE_DELETE);
        intentFilter.addAction(ACTION_SCENE_TASK_RESTART);
        intentFilter.addAction(ACTION_SCENE_CPU_TASK);
        mContext.registerReceiver(mReceiver, intentFilter);

        IntentFilter pkgFilter = new IntentFilter();
        pkgFilter.addDataScheme("package");
        pkgFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
        pkgFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
        mContext.registerReceiver(mPackageChangeReceiver, pkgFilter);
        //检查之前是否存在重启机制
        long restartTime = SceneSharedPrefManager.getSceneRestartTime();
        if (restartTime != 0) {
            //按照预先设置的时间，重新定时
            Intent taskIntent = new Intent(ACTION_SCENE_TASK_RESTART);
            PendingIntent pendingIntent = PendingIntent
                    .getBroadcast(mContext, 0, taskIntent, PendingIntent.FLAG_UPDATE_CURRENT);
            AlarmManager alarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
            alarmManager.cancel(pendingIntent);
            alarmManager.set(AlarmManager.RTC_WAKEUP, restartTime, pendingIntent);
            if (FeatureConfig.DEBUG_LOG) {
                LogHelper.d("Scene", "场景化检查机制将会重启于 " + DateUtils.getRelativeTimeSpanString(mContext, restartTime));
            }
        } else {
            start();
        }
        cpuScan();
        SceneBatteryChange.getInstance().start();
        //应用专清界面
        //scheduleAppCleanTask();
    }

    private void start() {
        SceneScreenSwitchReceiver.getInstance().start();
        ScenePeriodTaskReceiver.getInstance().start();
    }

    private void restart() {
        SceneSharedPrefManager.setSceneRestartTime(0);
        start();
        if (FeatureConfig.DEBUG_LOG) {
            LogHelper.d("Scene", "场景化检测重启完成 ");
        }
    }

    //通知栏弹出后在无效时间间隔内或者达到一天上限之后，停止所有的后台检查任务以提高性能
    private void stopSceneCheckTask() {
        mHandler.removeCallbacksAndMessages(null);
        ScenePeriodTaskReceiver.getInstance().stop();
        SceneScreenSwitchReceiver.getInstance().stop();

        long interval = SceneSharedPrefManager.getNotificationInterval() * SceneConstants.HOUR_MS;
        Calendar calendar = Calendar.getInstance();
        int localShowCount = SceneSharedPrefManager.getNotificationShowCount();
        int maxShowCount = SceneSharedPrefManager.getNotificationMaxCount();
        long now = System.currentTimeMillis();
        long triggerTime;
        if (localShowCount >= maxShowCount) {
            calendar.setTimeInMillis(now);
            calendar.add(Calendar.DAY_OF_MONTH, 1);
            calendar.add(Calendar.HOUR_OF_DAY, 1);
            triggerTime = calendar.getTimeInMillis();
        } else {
            triggerTime = now + interval;
        }

        //预设最小时间间隔，应该为1h,避免配置出错过度重启
        if ((triggerTime - now) >= SceneConstants.HOUR_MS) {
            Intent taskIntent = new Intent(ACTION_SCENE_TASK_RESTART);
            PendingIntent pendingIntent = PendingIntent
                    .getBroadcast(mContext, 0, taskIntent, PendingIntent.FLAG_UPDATE_CURRENT);
            AlarmManager alarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
            alarmManager.cancel(pendingIntent);
            alarmManager.set(AlarmManager.RTC_WAKEUP, triggerTime, pendingIntent);
            SceneSharedPrefManager.setSceneRestartTime(triggerTime);

            if (FeatureConfig.DEBUG_LOG) {
                calendar.setTimeInMillis(triggerTime);
                LogHelper
                        .d("Scene", "注意，场景化检查机制停止，将会重启于 " + DateUtils.getRelativeTimeSpanString(mContext, triggerTime));
            }
        }
    }

    public static NotificationSceneManager getInstance() {
        if (mManagerInstance == null) {
            synchronized (NotificationSceneManager.class) {
                if (mManagerInstance == null) {
                    mManagerInstance = new NotificationSceneManager();
                    mManagerInstance.init();
                }
            }
        }
        return mManagerInstance;
    }

    /**
     * 场景化消息通用控制，每次触发场景前先进行检查
     */
    public boolean checkAndRestTimeLimit() {
        if (FeatureConfig.DEBUG_LOG) {
            LogHelper.d(TAG, "场景化消息通用控制检查开始");
        }

        //判断相邻两条消息时间间隔
        long lastNotificationShow = SceneSharedPrefManager.getLastNotificationShowTime();
        long interval = SceneSharedPrefManager.getNotificationInterval() * SceneConstants.HOUR_MS;
        if (System.currentTimeMillis() - lastNotificationShow < interval) {
            if (FeatureConfig.DEBUG_LOG) {
                LogHelper.d(TAG, "----相邻两次场景化时间间隔小于 " + interval / SceneConstants.HOUR_MS + " hours, 无法展示");
            }
            stopSceneCheckTask();
            return false;
        }

        //同一天内最大消息次数限制
        Calendar calendar = Calendar.getInstance();
        int currentDay = calendar.get(Calendar.DAY_OF_MONTH);
        int currentMonth = calendar.get(Calendar.MONTH);
        int currentYear = calendar.get(Calendar.YEAR);
        calendar.setTimeInMillis(lastNotificationShow);
        int lastDay = calendar.get(Calendar.DAY_OF_MONTH);
        int lastMonth = calendar.get(Calendar.MONTH);
        int lastYear = calendar.get(Calendar.YEAR);
        int localShowCount = SceneSharedPrefManager.getNotificationShowCount();
        int maxShowCount = SceneSharedPrefManager.getNotificationMaxCount();
        if (currentYear == lastYear && lastMonth == currentMonth && lastDay == currentDay) {
            if (FeatureConfig.DEBUG_LOG) {
                LogHelper.d(TAG,
                        "----同一天内，已经展示：" + localShowCount + ",最大展示：" + maxShowCount + ",是否可以展示：" + (localShowCount
                                < maxShowCount));
            }
            boolean canShow = localShowCount < maxShowCount;
            if (!canShow) {
                stopSceneCheckTask();
            }
            return canShow;
        } else if (currentYear > lastYear
                || (currentYear == lastYear && currentMonth > lastMonth)
                || (currentYear == lastYear && currentMonth == lastMonth && currentDay > lastDay)) {
            if (maxShowCount == 0) {
                if (FeatureConfig.DEBUG_LOG) {
                    LogHelper.d(TAG, "----配置展示次数为0，不可展示");
                }
                return false;
            }
            if (FeatureConfig.DEBUG_LOG) {
                LogHelper.d(TAG, "----超过一天，可以展示");
            }
            SceneSharedPrefManager.setNotificationShowCount(0);
            return true;
        }
        return false;
    }

    public void showSceneNotification(NotificationBaseItem item) {
        Notification notice = item.prepareNotification();
        SceneType sceneType = SceneToolkit.getCurrentAplusScene(mContext);
        if (SceneType.APP_CLEAN == item.getSceneType()) {
            mNotifyManage.notify(APPLCEAN_NOTIFICATION_ID, notice);
        } else if (item.getSceneType() == sceneType) {
            mNotifyManage.notify(APLUS_NOTIFICATIONID, notice);
        } else {
            cancelSceneNotification();
            mNotifyManage.notify(NOTIFICATION_ID, notice);
        }
        afterSceneNotificationShow(item);
    }

    /**
     * 场景化通知栏消息展示后的系列操作，包括展示计数、时间记录、活跃上报等
     */
    public void afterSceneNotificationShow(NotificationBaseItem item) {
        SceneType sceneType = item.getSceneType();
        long now = System.currentTimeMillis();
        SceneSharedPrefManager.setLastSceneShowTime(sceneType, now);
        if (ScenePriority.A_PLUS != sceneType.priority) {
            SceneSharedPrefManager.setLastNotificationShowTime(now);
            int oldCount = SceneSharedPrefManager.getNotificationShowCount();
            SceneSharedPrefManager.setNotificationShowCount(oldCount + 1);
            SceneSharedPrefManager.setCurrentShowSceneType(sceneType);
            stopSceneCheckTask();
        }
    }

    public static void cancelSceneNotification() {
        NotificationManager notificationManager = (NotificationManager) CleanApplication.getInstance()
                .getSystemService(Context.NOTIFICATION_SERVICE);
        notificationManager.cancel(NOTIFICATION_ID);
        SceneSharedPrefManager.setCurrentShowSceneType(null);
    }

    public void setNetflowShowPkg(String pkg) {
        mNetflowShowPkg = pkg;
    }

    private BroadcastReceiver mPackageChangeReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String pkgName = URI.create(intent.getDataString()).getSchemeSpecificPart();
            boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
            String action = intent.getAction();
            if (FeatureConfig.DEBUG_LOG) {
                LogHelper.d(TAG, "removed pkg= " + pkgName + "  action = " + action);
            }
            if (Intent.ACTION_PACKAGE_REMOVED.equals(action) && !replacing) {
                onPackageRemove(pkgName);
            }
        }
    };

    private void onPackageRemove(String pkg) {
        if (TextUtils.isEmpty(pkg)) {
            return;
        }
        NotificationManager nMgr = (NotificationManager) CleanApplication.getInstance().getSystemService(Context.NOTIFICATION_SERVICE);
        if (pkg.equals(mNetflowShowPkg)) {
            nMgr.cancel(NOTIFICATION_ID);
            mNetflowShowPkg = "";
        }
    }

    public void post(Runnable runnable) {
        mHandler.post(runnable);
    }

    public void postDelayed(Runnable runnable, long delayMillis) {
        mHandler.postDelayed(runnable, delayMillis);
    }


    private void cpuScan() {
        SceneType aplusType = SceneToolkit.getCurrentAplusScene(mContext);
        if (SceneType.BG_CPU_OVERLOAD == aplusType) {
            mCpuHandler = mAPlusHandler;
        } else {
            mCpuHandler = mHandler;
        }
        mCpuHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                mContext.sendBroadcast(new Intent(ACTION_SCENE_CPU_TASK));
            }
        }, SCENE_CPUREALTIME_LONG_LAPSE_MS);
        if (SceneType.BAT_SHARPDEC == aplusType) {
            if (SceneSharedPrefManager.getSceneRestartTime() != 0) {
                if (FeatureConfig.DEBUG_LOG) {
                    LogHelper.d(TAG, "场景化检测已经停止，无需再安排cpu检查任务 ");
                }
                return;
            }
        }

        if (FeatureConfig.DEBUG_LOG) {
            LogHelper.d(TAG, "场景-总Cpu占用高，检查开始");
        }
        SceneToolkit.sLastCpuAll = 0;
        SceneToolkit.sLastCpuIdle = 0;
        mCpuScanIndex = 0;
        mCpuHandler.post(mCpuCheckRunnable);
    }

    private Handler mCpuHandler;
    private static final int SCENE_CPUREALTIME_SHORT_LAPSE_MS = 5 * 1000;
    private static final int SCENE_CPUREALTIME_LONG_LAPSE_MS = 2 * 60 * 1000;
    private int mCpuScanIndex = 0;//cpu扫描计数
    private Runnable mCpuCheckRunnable = new Runnable() {

        private static final int CHECK_COUNT = 3;//检查N次,第一次确定起点,取剩余的值求平均
        private int[] resultArray = new int[CHECK_COUNT];

        @Override
        public void run() {
            if (mCpuScanIndex >= CHECK_COUNT) {
                if (FeatureConfig.DEBUG_LOG) {
                    LogHelper.d(TAG, "----第0次cpu : " + resultArray[0]);
                }
                int sum = 0;
                for (int i = 1; i < CHECK_COUNT; i++) {
                    if (FeatureConfig.DEBUG_LOG) {
                        LogHelper.d(TAG, "----第" + i + "次cpu : " + resultArray[i]);
                    }
                    sum += resultArray[i];
                }
                int averageCpuUsage = sum / (CHECK_COUNT - 1);
                NotificationBaseItem totalCpuItem = new TotalCpuUtilizationItem(averageCpuUsage);
                if (totalCpuItem.checkRules()) {
                    NotificationSceneManager.getInstance().showSceneNotification(totalCpuItem);
                }
            } else {
                int cpuUsage = SceneToolkit.calculateCpu();
                resultArray[mCpuScanIndex++] = cpuUsage;
                mCpuHandler.postDelayed(this, SCENE_CPUREALTIME_SHORT_LAPSE_MS);
            }
        }
    };
}
